home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / ole2book.zip / CHAP07.ZIP / CHAP07 / PATRON / PAGEMOUS.CPP < prev    next >
C/C++ Source or Header  |  1993-06-07  |  12KB  |  509 lines

  1. /*
  2.  * PAGEMOUS.CPP
  3.  * New for Chapter 7
  4.  *
  5.  * Implementation of mouse-related member functions of CPage.
  6.  * The remainder is in PAGE.CPP.  This separate file keeps this
  7.  * grungy hit-testing/drawing code out of our way.
  8.  *
  9.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Software Design Engineer
  12.  * Microsoft Systems Developer Relations
  13.  *
  14.  * Internet  :  kraigb@microsoft.com
  15.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  16.  */
  17.  
  18.  
  19. #include "patron.h"
  20.  
  21.  
  22. //Lookups into the array using g_rgHTCode[x+y*3] in PAGEMOUS.CPP
  23. #define YTOP            0
  24. #define YMID            1
  25. #define YBOT            2
  26. #define XLEFT           0
  27. #define XMID            1
  28. #define XRIGHT          2
  29.  
  30. //Values to restrict sizing in CPage::OnMouseMove
  31. #define SIZINGTOP       0x0001
  32. #define SIZINGBOTTOM    0x0002
  33. #define SIZINGLEFT      0x0004
  34. #define SIZINGRIGHT     0x0008
  35.  
  36.  
  37. //This array is for hit-testing lookups
  38. static UINT g_rgHTCode[9]={HTTOPLEFT, HTTOP, HTTOPRIGHT
  39.     , HTLEFT, HTCLIENT, HTRIGHT, HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT};
  40.  
  41.  
  42. //This is for restricting tracking based on the hit-test
  43. static UINT g_rguSizingFlags[9]={SIZINGTOP | SIZINGLEFT, SIZINGTOP
  44.     , SIZINGTOP | SIZINGRIGHT, SIZINGLEFT, 0, SIZINGRIGHT
  45.     , SIZINGBOTTOM | SIZINGLEFT, SIZINGBOTTOM, SIZINGBOTTOM | SIZINGRIGHT};
  46.  
  47.  
  48.  
  49. /*
  50.  * CPage::OnLeftDown
  51.  *
  52.  * Purpose:
  53.  *  Called when the user clicks with the left button on this page.
  54.  *  We find the object under that position that is visibly on top
  55.  *  (always the first one under this location in the page list since
  56.  *  we paint in reverse order) and select it.
  57.  *
  58.  * Parameters:
  59.  *  uKeys           UINT carrying the key state.
  60.  *  x, y            UINT coordinates of the click in device units.
  61.  *
  62.  * Return Value:
  63.  *  BOOL            Indicates if the action changed the object.
  64.  */
  65.  
  66. BOOL CPage::OnLeftDown(UINT uKeys, UINT x, UINT y)
  67.     {
  68.     UINT        iTenant;
  69.     LPTENANT    pTenant;
  70.     RECT        rc;
  71.  
  72.     /*
  73.      * See if we have to start sizing (which always happens on current
  74.      * tenant).  m_uHTCode is set in OnNCHitTest below.
  75.      */
  76.     if (HTNOWHERE!=m_uHTCode && HTCLIENT!=m_uHTCode)
  77.         {
  78.         //We are sizing, so start tracking
  79.         m_pTenantCur->RectGet(&m_rcl, TRUE);
  80.         SetCapture(m_hWnd);
  81.         m_fTracking=TRUE;
  82.  
  83.         m_hDC=GetDC(m_hWnd);
  84.  
  85.         //Place the rectangle exactly where it is on the screen.
  86.         RECTFROMRECTL(rc, m_rcl)
  87.         OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);
  88.         RECTLFROMRECT(m_rcl, rc);
  89.         m_rclOrg=m_rcl;
  90.  
  91.         DrawFocusRect(m_hDC, &rc);
  92.  
  93.         m_pPG->CalcBoundingRect(&rc, TRUE);
  94.         RECTLFROMRECT(m_rclBounds, rc);
  95.         return FALSE;
  96.         }
  97.  
  98.     iTenant=TenantFromPoint(x, y, &pTenant);
  99.  
  100.     if (NULL==pTenant)
  101.         return FALSE;
  102.  
  103.     //If this one is already current, we might be now sizing.
  104.     if (pTenant==m_pTenantCur)
  105.         return FALSE;
  106.  
  107.     //Deselect the current tenant
  108.     if (NULL!=m_pTenantCur)
  109.         m_pTenantCur->Select(FALSE);
  110.  
  111.     //Move this tenant to the top of the list
  112.     m_iTenantCur=0;
  113.  
  114.     SendMessage(m_hWndTenantList, LB_DELETESTRING, iTenant, 0L);
  115.     SendMessage(m_hWndTenantList, LB_INSERTSTRING, 0, (LONG)pTenant);
  116.  
  117.     //Select and repaint the new tenant to show it up front
  118.     m_pTenantCur=pTenant;
  119.  
  120.     m_pTenantCur->Repaint();
  121.     m_pTenantCur->Select(TRUE);
  122.  
  123.     return FALSE;
  124.     }
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131. /*
  132.  * CPage::OnLeftUp
  133.  *
  134.  * Purpose:
  135.  *  Called when the user clicks up with the left button on this page.
  136.  *  We stop tracking on this message, if necessary, and resize the object.
  137.  *
  138.  * Parameters:
  139.  *  uKeys           UINT carrying the key state.
  140.  *  x, y            UINT coordinates of the click in device units.
  141.  *
  142.  * Return Value:
  143.  *  BOOL            Indicates if this action changed the object.
  144.  */
  145.  
  146. BOOL CPage::OnLeftUp(UINT uKeys, UINT x, UINT y)
  147.     {
  148.     RECT    rc, rcT;
  149.  
  150.     if (!m_fTracking)
  151.         return FALSE;
  152.  
  153.     //Remove the dotted rectangle.
  154.     RECTFROMRECTL(rc, m_rcl)
  155.     DrawFocusRect(m_hDC, &rc);
  156.     ReleaseDC(m_hWnd, m_hDC);
  157.  
  158.     ReleaseCapture();
  159.     m_fTracking=FALSE;
  160.  
  161.     //If the original and new rects are the same, nothing happened.
  162.     RECTFROMRECTL(rcT, m_rclOrg);
  163.  
  164.     if (EqualRect(&rc, &rcT))
  165.         return FALSE;
  166.  
  167.     RECTFROMRECTL(rcT, m_rclOrg);
  168.     InvalidateRect(m_hWnd, &rcT, TRUE);
  169.  
  170.     //Invalidate on the screen before accounting for scrolling
  171.     InvalidateRect(m_hWnd, &rc, TRUE);
  172.  
  173.     //Factor in the scrolling and tell the tenant where it now stands.
  174.     OffsetRect(&rc, (int)m_pPG->m_xPos, (int)m_pPG->m_yPos);
  175.     RECTLFROMRECT(m_rcl, rc);
  176.     m_pTenantCur->RectSet(&m_rcl, TRUE);
  177.  
  178.     UpdateWindow(m_hWnd);
  179.     return TRUE;
  180.     }
  181.  
  182.  
  183.  
  184.  
  185.  
  186. /*
  187.  * CPage::OnLeftDoubleClick
  188.  *
  189.  * Purpose:
  190.  *  Called when the user double-clicks with the left button on this page.
  191.  *  We find the object under that position that is visibly on top
  192.  *  (always the first one under this location in the page list since
  193.  *  we paint in reverse order) and activate it.
  194.  *
  195.  * Parameters:
  196.  *  uKeys           UINT carrying the key state.
  197.  *  x, y            UINT coordinates of the click in device units.
  198.  *
  199.  * Return Value:
  200.  *  BOOL            Indicates if the action changed the object.
  201.  */
  202.  
  203. BOOL CPage::OnLeftDoubleClick(UINT uKeys, UINT x, UINT y)
  204.     {
  205.     /*
  206.      * The current tenant is the only one that can be activated, so
  207.      * we just have to make sure the mouse is there.  For that we can
  208.      * use the last hit-test code we saw since it's updated on every
  209.      * mouse move.
  210.      */
  211.  
  212.     if (HTNOWHERE!=m_uHTCode)
  213.         return m_pTenantCur->Activate(OLEIVERB_PRIMARY);
  214.  
  215.     return FALSE;
  216.     }
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223. /*
  224.  * CPage::OnNCHitTest
  225.  *
  226.  * Purpose:
  227.  *  Processes WM_NCHITTEST on a page so we can check for hits on the
  228.  *  handles of the selected object for resizing.  We only save information
  229.  *  for ourselves and do not interfere with normal hit-testing.
  230.  *
  231.  * Parameters:
  232.  *  x, y            UINT device coordinates to check.
  233.  *
  234.  * Return Value:
  235.  *  None
  236.  */
  237.  
  238. void CPage::OnNCHitTest(UINT x, UINT y)
  239.     {
  240.     RECT        rc;
  241.     RECTL       rcl;
  242.     int         iMid1, iMid2;
  243.     int         xHit, yHit;
  244.     POINT       pt;
  245.     int         x0, y0;
  246.  
  247.     //By default we won't start sizing on a click and don't hit an object.
  248.     m_uSizingFlags=0;
  249.     m_uHTCode=HTNOWHERE;
  250.  
  251.     if (NULL==m_pTenantCur)
  252.         return;
  253.  
  254.     //Convert device points to our coordinates
  255.     m_pTenantCur->RectGet(&rcl, FALSE);
  256.     RECTFROMRECTL(rc, rcl);
  257.     RectConvertMappings(&rc, NULL, TRUE);
  258.     OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);
  259.  
  260.     SETPOINT(pt, x, y);
  261.     ScreenToClient(m_hWnd, &pt);
  262.     x0=pt.x;
  263.     y0=pt.y;
  264.  
  265.     if (x0 < rc.left || x0 > rc.right)
  266.         return;
  267.  
  268.     if (y0 < rc.top || y0 > rc.bottom)
  269.         return;
  270.  
  271.     //It's at least in the object.
  272.     m_uHTCode=HTCLIENT;
  273.  
  274.     //Check for hits in horizontal regions
  275.     xHit=-1;
  276.     iMid1=rc.left+((rc.right-rc.left-CXYHANDLE) >> 1);
  277.     iMid2=rc.left+((rc.right-rc.left+CXYHANDLE) >> 1);
  278.  
  279.     if (x0 >= rc.left && x0 <= rc.left+CXYHANDLE)
  280.         xHit=XLEFT;
  281.     else if (x0 >= iMid1 && x0 <= iMid2)
  282.         xHit=XMID;
  283.     else if (x0 >= rc.right-CXYHANDLE && x0 <= rc.right)
  284.         xHit=XRIGHT;
  285.  
  286.     if (-1==xHit)
  287.         return;
  288.  
  289.     //Check for hits in vertical regions
  290.     yHit=-1;
  291.     iMid1=rc.top+((rc.bottom-rc.top-CXYHANDLE) >> 1);
  292.     iMid2=rc.top+((rc.bottom-rc.top+CXYHANDLE) >> 1);
  293.  
  294.     if (y0 >= rc.top && y0 <= rc.top+CXYHANDLE)
  295.         yHit=YTOP;
  296.     else if (y0 >= iMid1 && y0 <= iMid2)
  297.         yHit=YMID;
  298.     else if (y0 >= rc.bottom-CXYHANDLE && y0 <= rc.bottom)
  299.         yHit=YBOT;
  300.  
  301.     if (-1==yHit)
  302.         return;
  303.  
  304.     //We hit a handle, so save our HT code
  305.     m_uSizingFlags=g_rguSizingFlags[xHit+(yHit*3)];
  306.     m_uHTCode=g_rgHTCode[xHit+(yHit*3)];
  307.     return;
  308.     }
  309.  
  310.  
  311.  
  312.  
  313.  
  314. /*
  315.  * CPage::SetCursor
  316.  *
  317.  * Purpose:
  318.  *  Processes WM_SETCURSOR using the code from OnNCHitTest.
  319.  *
  320.  * Parameters:
  321.  *  x, y            UINT device coordinates to check.
  322.  *
  323.  * Return Value:
  324.  *  LRESULT         HT* code for Windows.
  325.  */
  326.  
  327. BOOL CPage::OnSetCursor(UINT uHTCode)
  328.     {
  329.     HCURSOR     hCur;
  330.     UINT        iCur;
  331.  
  332.     //We really just ignore uHTCode and use the one we saved in OnNCHitTest
  333.  
  334.     switch (m_uHTCode)
  335.         {
  336.         case HTTOP:
  337.         case HTBOTTOM:
  338.             iCur=IDC_VARROWS;
  339.             break;
  340.  
  341.         case HTLEFT:
  342.         case HTRIGHT:
  343.             iCur=IDC_HARROWS;
  344.             break;
  345.  
  346.  
  347.         case HTTOPLEFT:
  348.         case HTBOTTOMRIGHT:
  349.             iCur=IDC_NWSEARROWS;
  350.             break;
  351.  
  352.         case HTTOPRIGHT:
  353.         case HTBOTTOMLEFT:
  354.             iCur=IDC_NESWARROWS;
  355.             break;
  356.  
  357.         default:
  358.             return FALSE;
  359.         }
  360.  
  361.     hCur=UICursorLoad(iCur);
  362.     SetCursor(hCur);
  363.  
  364.     return TRUE;
  365.     }
  366.  
  367.  
  368.  
  369.  
  370.  
  371. /*
  372.  * CPage::OnMouseMove
  373.  *
  374.  * Purpose:
  375.  *  Processes WM_MOUSEMOVE on a page so we can handle tracking resize
  376.  *  of a tenant.
  377.  *
  378.  * Parameters:
  379.  *  x, y            UINT device coordinates to check.
  380.  *
  381.  * Return Value:
  382.  *  LRESULT         HT* code for Windows.
  383.  */
  384.  
  385.  
  386. void CPage::OnMouseMove(UINT uKeys, int x, int y)
  387.     {
  388.     RECT        rc, rcO, rcB;
  389.     int         cxy;
  390.  
  391.     if (!m_fTracking)
  392.         return;
  393.  
  394.     //Get rid of the old rectangle.
  395.     RECTFROMRECTL(rc, m_rcl)
  396.     DrawFocusRect(m_hDC, &rc);
  397.  
  398.     /*
  399.      * Calculate the new.  The flags in m_uSizingFlags tell us what to
  400.      * change.  We limit the object by the page margins and a minimum
  401.      * size of 3*CXYHANDLE in either dimension.
  402.      */
  403.     cxy=3*CXYHANDLE;
  404.  
  405.     RECTFROMRECTL(rcO, m_rclOrg);
  406.     RECTFROMRECTL(rcB, m_rclBounds);
  407.  
  408.     if (m_uSizingFlags & SIZINGTOP)
  409.         {
  410.         if (y >= rcO.bottom-cxy)
  411.             y=rcO.bottom-cxy;
  412.  
  413.         if (y <= rcB.top)           //Limit to top of page.
  414.             y=rcB.top;
  415.  
  416.         m_rcl.top=y;
  417.         }
  418.  
  419.     if (m_uSizingFlags & SIZINGBOTTOM)
  420.         {
  421.         if (y <= rcO.top+cxy)
  422.             y=rcO.top+cxy;
  423.  
  424.         if (y >= rcB.bottom)         //Limit to bottom of page.
  425.             y=rcB.bottom;
  426.  
  427.         m_rcl.bottom=y;
  428.         }
  429.  
  430.     if (m_uSizingFlags & SIZINGLEFT)
  431.         {
  432.         if (x >= rcO.right-cxy)
  433.             x=rcO.right-cxy;
  434.  
  435.         if (x <= rcB.left)           //Limit to left of page.
  436.             x=rcB.left;
  437.  
  438.         m_rcl.left=x;
  439.         }
  440.  
  441.     if (m_uSizingFlags & SIZINGRIGHT)
  442.         {
  443.         if (x <= rcO.left+cxy)
  444.             x=rcO.left+cxy;
  445.  
  446.         if (x >= rcB.right)          //Limit to right of page.
  447.             x=rcB.right;
  448.  
  449.         m_rcl.right=x;
  450.         }
  451.  
  452.  
  453.     //Draw the new
  454.     RECTFROMRECTL(rc, m_rcl)
  455.     DrawFocusRect(m_hDC, &rc);
  456.  
  457.     return;
  458.     }
  459.  
  460.  
  461.  
  462.  
  463. /*
  464.  * CPage::TenantFromPoint
  465.  * (Protected)
  466.  *
  467.  * Purpose:
  468.  *  Finds the tenant under the given device coordinates on this page.
  469.  *
  470.  * Parmeters:
  471.  *  x, y            UINT coordinates.
  472.  *  ppTenant        LPTENANT FAR * in which to return the pointer.
  473.  *
  474.  * Return Value:
  475.  *  UINT            Index of the matched tenant, 0xFFFF if not found.
  476.  */
  477.  
  478. UINT CPage::TenantFromPoint(UINT x, UINT y, LPTENANT FAR *ppTenant)
  479.     {
  480.     LPTENANT    pTenant;
  481.     RECTL       rcl;
  482.     UINT        i;
  483.     int         x0, y0;
  484.  
  485.     x0=x+m_pPG->m_xPos;
  486.     y0=y+m_pPG->m_yPos;
  487.  
  488.     for (i=0; i < m_cTenants; i++)
  489.         {
  490.         if (!FTenantGet(i, &pTenant, FALSE))
  491.             continue;
  492.  
  493.         pTenant->RectGet(&rcl, TRUE);
  494.  
  495.         //Essentially Perform PointInRECTL
  496.         if (x0 >= rcl.left && x0 <= rcl.right)
  497.             {
  498.             if (y0 <=rcl.bottom && y0 >=rcl.top)
  499.                 {
  500.                 *ppTenant=pTenant;
  501.                 return i;
  502.                 }
  503.             }
  504.         }
  505.  
  506.     *ppTenant=NULL;
  507.     return 0xFFFF;
  508.     }
  509.